package com.cloudbroker.bcs.common.t2sdk.client;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.cloudbroker.bcs.common.t2sdk.constants.T2Fields;
import com.cloudbroker.bcs.common.t2sdk.constants.T2SysFields;
import com.cloudbroker.bcs.common.t2sdk.util.T2SdkUtil;
import com.cloudbroker.bcs.common.t2sdk.util.T2VOUtil;
import com.cloudbroker.bcs.common.util.ValueUtil;
import com.hundsun.t2sdk.common.core.context.ContextUtil;
import com.hundsun.t2sdk.common.share.dataset.DatasetService;
import com.hundsun.t2sdk.impl.client.T2Services;
import com.hundsun.t2sdk.interfaces.IClient;
import com.hundsun.t2sdk.interfaces.T2SDKException;
import com.hundsun.t2sdk.interfaces.share.dataset.IDataset;
import com.hundsun.t2sdk.interfaces.share.dataset.IDatasets;
import com.hundsun.t2sdk.interfaces.share.event.EventReturnCode;
import com.hundsun.t2sdk.interfaces.share.event.EventTagdef;
import com.hundsun.t2sdk.interfaces.share.event.EventType;
import com.hundsun.t2sdk.interfaces.share.event.IEvent;

public class T2Client {
    
    private static final Logger LOG = LoggerFactory.getLogger(T2Client.class);
    
    private static final String DEFAULT_NODE_NAME = "_DEFAULT_";
    
    private static T2Services t2Services;
    
    private static Lock t2ServicesLock = new ReentrantLock();
    
    private static T2Services getT2Services() throws T2SDKException {
        if (null == t2Services) {
            t2ServicesLock.lock();
            try {
                if (null == t2Services) {
                    T2Services t2Services = T2Services.getInstance();
                    t2Services.init();
                    t2Services.start();
                    T2Client.t2Services = t2Services;
                }
            } finally {
                t2ServicesLock.unlock();
            }
        }
        return t2Services;
    }
    
    private static IClient getClient(String nodeName) {
        try {
            return getT2Services().getClient(nodeName);
        } catch (T2SDKException e) {
            throw new RuntimeException("init t2sdk failed", e);
        }
    }
    
    private static IClient getClient() {
        return getClient(DEFAULT_NODE_NAME);
    }
    
    public static Map<String, Object> callT2(String functionId, Map<String, Object> param) {
        return callT2(functionId, param, false);
    }
    
    public static Map<String, Object> callT2(String functionId, Map<String, Object> param, boolean forceList) {
        // 构造请求事件
        IEvent event = ContextUtil.getServiceContext().getEventFactory()
                .getEventByAlias(functionId, EventType.ET_REQUEST);
        
        String compId = ValueUtil.getString(param.remove(T2SysFields.COMP_ID), null);
        if (null != compId) {
            event.setStringArrayAttributeValue(EventTagdef.TAG_JRES_ROUTE_INFO, new String[] { compId });
        }
        
        // 构造请求参数
        IDataset paramDataset = T2SdkUtil.toDataset(param);
        if (LOG.isDebugEnabled()) {
            System.out.println('[' + functionId + "]paramDataset: ");
            DatasetService.printDataset(paramDataset);
        }
        event.putEventData(paramDataset);
        
        // 同步调用服务
        IClient client = getClient();
        IEvent resultEvt = null;
        try {
            resultEvt = client.sendReceive(event);
        } catch (Exception e) {
            LOG.error("call T2 failed", e);
            return null;
        }
        
        return handleResultEvent(functionId, resultEvt, forceList);
    }
    
    private static Map<String, Object> handleResultEvent(String functionId, IEvent resultEvt, boolean forceList) {
        // 解析datasets
        IDatasets dss = resultEvt.getEventDatas();
        Map<String, Object> result = null;
        if (null == dss) {
            result = new HashMap<String, Object>();
        } else {
            int dsc = dss.getDatasetCount();
            if (1 > dsc) {
                result = new HashMap<String, Object>();
            } else {
                if (1 < dsc) {
                    LOG.warn("more than one dataset, only take first");
                }
                IDataset ds = dss.getDataset(0);
                if (LOG.isDebugEnabled()) {
                    System.out.println('[' + functionId + "]resultDataset: ");
                    DatasetService.printDataset(ds);
                }
                int rc = ds.getRowCount();
                if (1 < rc || forceList) {
                    List<Map<String, Object>> resultList = T2SdkUtil.toListMap(ds);
                    result = new HashMap<String, Object>();
                    result.put(T2Fields.RESULT_LIST, resultList);
                } else if (1 == rc) {
                    result = T2SdkUtil.toMap(ds);
                } else {
                    result = new HashMap<String, Object>();
                }
            }
        }
        
        // 根据returnCode、errorNo两个tag，或error_no字段来处理结果
        int returnCode = resultEvt.getReturnCode();
        if (EventReturnCode.I_OK == returnCode) { // 业务正常
            if (!result.containsKey(T2Fields.ERROR_NO)) {
                T2VOUtil.setSuccessResult(result, ValueUtil.getString(result.get(T2Fields.ERROR_INFO)));
            }
            return result;
        } else {
            if (!result.containsKey(T2Fields.ERROR_NO)) {
                String errorNo = resultEvt.getErrorNo();
                if ("0".equals(errorNo)) {
                    return T2VOUtil.genErrorResult(String.valueOf(returnCode), "");
                } else {
                    return T2VOUtil.genErrorResult(errorNo, resultEvt.getErrorInfo());
                }
            } else {
                return T2VOUtil.genErrorResult(String.valueOf(result.get(T2Fields.ERROR_NO)),
                        ValueUtil.getString(result.get(T2Fields.ERROR_INFO)));
            }
        }
    }
    
}
